package com.superquan.selfstudybootmybatis.utils.singleton;

/**
 * @program: self-study-bootmybatis
 * @ClassName DoubleRetrievalPattern
 * @description: 双重校验锁实现单例模式
 * @author: zwq
 * 优点：线程安全，且保证了只有第一次调用单例时才会做同步，避免了每次都同步的性能消耗。（所谓的同步就是加了synchronized锁，相比懒汉模式，这个性能消耗较少）
 * 缺点：双重锁降低了程序的响应速度和性能
 **/
public class DoubleRetrievalPattern {

    //使用volatile修饰，防止发生指令重排序
    private static volatile DoubleRetrievalPattern doubleRetrievalPattern;

    private DoubleRetrievalPattern() {
        System.out.println("私有DoubleRetrievalPattern构造参数初始化");
    }

    public static DoubleRetrievalPattern getInstance() {
        if (doubleRetrievalPattern == null) {
            //使用synchronized修饰代码块，保证了线程安全
            //加锁同步，相比懒汉模式在方法中加synchronized，此处在代码块加锁，范围越小，性能影响越小
            synchronized (DoubleRetrievalPattern.class) {
                if (doubleRetrievalPattern == null) {
                    doubleRetrievalPattern = new DoubleRetrievalPattern();
                }
            }
        }
        return doubleRetrievalPattern;
    }

    public static void main(String[] args) {
        DoubleRetrievalPattern dp1 = DoubleRetrievalPattern.getInstance();
        DoubleRetrievalPattern dp2 = DoubleRetrievalPattern.getInstance();
        //"=="比较的是引用，若未true则说明lp1和lp2是同一个实例
        if(dp1==dp2){
            System.out.println("DoubleRetrievalPattern是使用双重检索创建的，因此lp1和lp2是同一个实例");
        }
    }
}
